﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using SHomeWorkshop.LunarConcept.Converters;
using System.Data.OleDb;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.Collections.ObjectModel;
using SHomeWorkshop.LunarConcept;
using SHomeWorkshop.LunarConcept.Enums;
using System.Windows.Media.Imaging;
using System.IO;
using System.Windows.Forms;

namespace SHomeWorkshop.LunarConcept
{

    /// <summary>
    /// 创建时间：2011年12月26日
    /// 创建者：  杨震宇
    /// =========================
    /// 主要用途：存放一些全局量。
    /// </summary>
    public class Globals
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]用于初始化相关属性值。
        /// </summary>
        static Globals()
        {
            #region 填充可用字体列表

            foreach (FontFamily ff in Fonts.SystemFontFamilies)
            {
                LanguageSpecificStringDictionary fontDics = ff.FamilyNames;
                var fontInfo = new FontInfo();
                string fontName = null;

                if (fontDics.ContainsKey(XmlLanguage.GetLanguage("zh-cn")))
                {
                    if (fontDics.TryGetValue(XmlLanguage.GetLanguage("zh-cn"), out fontName))
                    {
                        fontInfo.LocalFontName = fontName;
                    }
                }

                fontName = null;
                if (fontDics.TryGetValue(XmlLanguage.GetLanguage("en-us"), out fontName))
                {
                    fontInfo.FontName = fontName;//保证必有英文名。
                }

                systemFontInfosCollection.Add(fontInfo);
            }

            //systemFontInfosCollection.Sort();//不提供此方法。
            //systemFontInfosCollection.OrderBy(x => x.DefaultFontName);//无效，原因未知。

            //排序
            var fInfosList = from fontInfo in systemFontInfosCollection

                             orderby fontInfo.DefaultFontName descending

                             select fontInfo;

            systemFontInfosCollection = new ObservableCollection<FontInfo>(fInfosList);

            #endregion


            if (pathOfMyDocuments.EndsWith("\\") == false)
            {
                pathOfMyDocuments += "\\";
            }


            pathOfUserDirectory = pathOfMyDocuments + "SHome WorkShop\\" + AppFormatedName + "\\";
            if (System.IO.Directory.Exists(PathOfUserDirectory) == false)
            {
                System.IO.Directory.CreateDirectory(PathOfUserDirectory);
            }

            pathOfRecentlyFiles = pathOfUserDirectory + "RecentlyFiles.xml";
            pathofCmdKeymapFile = pathOfUserDirectory + "CmdKeyMap.xml";

            if (installedPath.EndsWith("\\") == false)
            {
                installedPath += "\\";
            }

            #region 模板文件路径

            pathOfUserTemplateDocuments = pathOfUserDirectory + "Templetes\\";

            pathOfUserTemplateDocuments = pathOfUserDirectory + "Templates\\";

            if (installedPath.EndsWith("\\"))
            {
                pathOfSystemTemplateDocuments = installedPath + "Templates\\";
            }
            else
            {
                pathOfSystemTemplateDocuments = installedPath + "\\Templates\\";
            }

            #endregion

            fullPathOfApp = installedPath + appName + ".exe";

            pathOfDataBase = pathOfUserDirectory + "LunarConcept.mdb";

            pathOfUserStyles = pathOfUserDirectory + "WidgetStyles\\";

            //初如化“命令输入窗口”背景画刷。
            textCommandInputBoxBackground = new VisualBrush();
            textCommandInputBoxBackground.TileMode = TileMode.None;
            textCommandInputBoxBackground.Stretch = Stretch.None;
            textCommandInputBoxBackground.AlignmentX = AlignmentX.Left;
            textCommandInputBoxBackground.AlignmentY = AlignmentY.Center;
            textCommandInputBoxBackground.Visual = new TextBlock()
            {
                Text = "..请在此处输入命令..",
                Foreground = Brushes.White,
            };

            thickConverter = new ThicknessConverter();

            //配置文件管理器初始化。
            configManager = new XmlConfigManager(PathOfUserDirectory + "config.xml");
        }

        #endregion

        private static readonly string appFullPath = System.Reflection.Assembly.GetEntryAssembly().Location;
        /// <summary>
        /// [静态只读]返回应用程序全路径。
        /// </summary>
        public static string AppFullPath
        {
            get { return Globals.appFullPath; }
        }

        /// <summary>
        /// 应用程序名，一般用作消息框的标题或窗口标题。
        /// 还可用下列方法：
        /// appName = System.Reflection.Assembly.GetEntryAssembly().Location;
        /// 上面这行返回：D:\My Documents\Visual Studio 2010\Projects\LunarConcept\LunarConcept\bin\Release\LunarConpect.exe
        /// Path.GetFileName(Assembly.GetEntryAssembly().GetName().CodeBase);//返回：LunarConcept.EXE
        /// </summary>
        private static readonly string appName = ((AssemblyTitleAttribute)Assembly.
            GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false)[0]).Title;
        /// <summary>
        /// [静态只读]返回应用程序（.exe文件）的短名，不含后缀名。
        /// </summary>
        public static string AppName
        {
            get { return Globals.appName; }
        }

        private static string appFormatedName = null;
        /// <summary>
        /// [只读]返回格式化的应用程序名。
        /// 格式化规则：在应用程序名中所有大写字母前面加上空格（首字母例外）。
        /// 例如：LunarConcept。格式化后为：Lunar Concept。
        /// </summary>
        public static string AppFormatedName
        {
            get
            {
                if (appFormatedName != null) return appFormatedName;

                StringBuilder sb = new StringBuilder();
                foreach (char c in appName)
                {
                    if (c >= 'A' && c <= 'Z')
                    {
                        sb.Append(' ');
                    }
                    sb.Append(c);
                }

                appFormatedName = sb.ToString().TrimStart(new char[] { ' ' });//移除首空格。
                return appFormatedName;
            }
        }

        private static string cmdParameterString = null;
        /// <summary>
        /// 静态属性，表示命令行参数中的第一个值。
        /// App.xmal.cs文件中Application_Startup事件处理器会写这个属性的值。
        /// 
        /// 程序启动时判断有没有传入这个属性的值，如果这个值指向一个磁盘上存在的合法文档，就以此文档初始化。
        /// </summary>
        internal static string CmdParameterString
        {
            get
            {
                return cmdParameterString;
            }
            set
            {
                cmdParameterString = value;
            }
        }

        private static readonly string documentName = "Lunar 概念图文档";
        /// <summary>
        /// [只读]返回程序自定义的文档类别的描述性（短）文本。
        /// ——值为“Lunar 概念图文档”。
        /// </summary>
        public static string DocumentName
        {
            get { return Globals.documentName; }
        }

        private static readonly string extensionName = "lcpt";
        /// <summary>
        /// [只读]返回程序自定义文档类别的后缀名。★不含“.”。
        /// ——值为“lcpt”。
        /// </summary>
        public static string ExtensionName
        {
            get { return Globals.extensionName; }
        }

        private static readonly string extensionNameOfOutportPng = "png";
        /// <summary>
        /// [只读]返回程序导出的图片文档后缀名（不含句点）。值为“png”。
        /// </summary>
        public static string ExtensionNameOfOutportPng
        {
            get { return Globals.extensionNameOfOutportPng; }
        }

        private static readonly string extensionNameOfTemplate = "lctmp";
        /// <summary>
        /// [只读]返回程序生成的模板文件的后缀名（不含句点）。
        /// </summary>
        public static string ExtensionNameOfTemplate
        {
            get { return Globals.extensionNameOfTemplate; }
        }

        private static string fullPathOfApp;
        /// <summary>
        /// [只读]返回应用程序运行时的全路径。
        /// </summary>
        public static string FullPathOfApp
        {
            get { return Globals.fullPathOfApp; }
        }

        private static OleDbConnection globalConnection;
        /// <summary>
        /// [读写]全局数据连接。
        /// </summary>
        public static OleDbConnection GlobalConnection
        {
            get { return Globals.globalConnection; }
            set { Globals.globalConnection = value; }
        }

        private static OleDbDataAdapter globalDataAdapter;
        /// <summary>
        /// [读写]数据适配器。用以从数据库中读取数据。
        /// </summary>
        public static OleDbDataAdapter GlobalDataAdapter
        {
            get { return Globals.globalDataAdapter; }
            set { Globals.globalDataAdapter = value; }
        }

        private static System.Data.DataSet globalDataSetIn = new System.Data.DataSet();
        /// <summary>
        /// [读写]数据集。
        /// </summary>
        public static System.Data.DataSet GlobalDataSetIn
        {
            get { return Globals.globalDataSetIn; }
            set { Globals.globalDataSetIn = value; }
        }

        private static string installedPath = System.AppDomain.CurrentDomain.BaseDirectory;
        /// <summary>
        /// [只读]取程序“安装（运行）目录”。
        /// </summary>
        public static string InstalledPath
        {
            get { return Globals.installedPath; }
        }

        /// <summary>
        /// 表示当前应用程序的主窗口。
        /// </summary>
        public static MainWindow MainWindow
        {
            get
            {
                MainWindow mainWindow = App.Current.MainWindow as MainWindow;
                return mainWindow;
            }
        }

        private static string pathofCmdKeymapFile;
        /// <summary>
        /// [只读]返回“自定义命令的快捷键映射表”（Xml文件）的文件全路径。
        /// </summary>
        public static string PathofCmdKeymapFile
        {
            get { return Globals.pathofCmdKeymapFile; }
        }

        private static string pathOfDataBase;
        /// <summary>
        /// [只读]数据文件路径。
        /// </summary>
        public static string PathOfDataBase
        {
            get { return Globals.pathOfDataBase; }
        }

        private static string pathOfUserStyles;
        /// <summary>
        /// [只读]用户自定义部件样式存储目录。
        /// </summary>
        public static string PathOfUserStyles
        {
            get { return Globals.pathOfUserStyles; }
        }

        private static readonly string pathOfMyDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        /// <summary>
        /// [只读]返回Windows操作系统中定义的“我的文档”这个特殊文件夹所指向的实际路径。
        /// </summary>
        public static string PathOfMyDocuments
        {
            get { return Globals.pathOfMyDocuments; }
        }

        private static string pathOfRecentlyFiles;
        /// <summary>
        /// [只读]指向本程序专用的一个Xml文档，此文档中保存了“最近打开的文件”列表。
        /// 此文档必定在“PathOfUserDirectory”目录下。
        /// </summary>
        public static string PathOfRecentlyFiles
        {
            get { return Globals.pathOfRecentlyFiles; }
        }

        private static string pathOfUserDirectory;
        /// <summary>
        /// [只读]返回自定义的只为本程序使用的“用户目录”的路径字符串（以"\"结尾）。
        /// </summary>
        public static string PathOfUserDirectory
        {
            get { return Globals.pathOfUserDirectory; }
        }

        private static string pathOfUserTemplateDocuments;
        /// <summary>
        /// [只读]用户模板文件夹。
        /// </summary>
        public static string PathOfUserTemplateDocuments
        {
            get { return Globals.pathOfUserTemplateDocuments; }
        }

        private static string pathOfSystemTemplateDocuments;
        /// <summary>
        /// [只读]系统模板文件夹。
        /// </summary>
        public static string PathOfSystemTemplateDocuments
        {
            get { return Globals.pathOfSystemTemplateDocuments; }
        }

        private static string outportImageSplitText = "<?Lunar Concept?>";
        /// <summary>
        /// [只读]导出png图片文件时，附加在尾部用以分隔图像数据与附加文本的字符串。
        /// </summary>
        public static string OutportImageSplitText
        {
            get { return Globals.outportImageSplitText; }
            set { Globals.outportImageSplitText = value; }
        }

        private static string sysFontFamily = "simsun";
        /// <summary>
        /// 默认系统字体名称。
        /// </summary>
        public static string SysFontFamily
        {
            get { return sysFontFamily; }
            set { sysFontFamily = value; }
        }

        /// <summary>
        /// 终于解决了输入法的问题。
        /// 原先使用WinForm的输入法控制库终究不行——取不出当前输入法名称。
        /// </summary>
        /// <param name="enable">开、关。</param>
        public static void SwitchInputMethod(bool enable)
        {
            //if (MainWindow == null) return;
            //InputMethod.SetIsInputMethodEnabled(MainWindow, false);
            //InputMethod.Current.ImeState = enable ? InputMethodState.On : InputMethodState.Off;
            // 旧版在 Win10 下效果不好

            if (MainWindow == null) return;

            if (enable)
            {
                //var typeOfLanguage = new System.Globalization.CultureInfo("zh-cn");
                //InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(typeOfLanguage);

                //InputMethod.SetIsInputMethodEnabled(MainWindow.ActiveTextEditor, enable);
                //InputMethod.Current.ImeState = InputMethodState.On;

                SwitchToLanguageMode("zh-CN");
            }
            else
            {
                //var typeOfLanguage = new System.Globalization.CultureInfo("en-us");
                //InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(typeOfLanguage);
                SwitchToLanguageMode("en-US");
            }
        }

        /// <summary>
        /// 切换输入法。来自：https://www.likecs.com/show-49021.html
        /// </summary>
        /// <param name="cultureType">语言项，如zh-CN，en-US</param>
        private static void SwitchToLanguageMode(string cultureType)
        {
            var installedInputLanguages = InputLanguage.InstalledInputLanguages;

            if (installedInputLanguages.Cast<InputLanguage>().Any(i => i.Culture.Name == cultureType))
            {
                InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(System.Globalization.CultureInfo.GetCultureInfo(cultureType));
            }
        }

        private static readonly VisualBrush textCommandInputBoxBackground;
        /// <summary>
        /// 给主窗口“命令输入框”使用的背景。
        /// </summary>
        public static VisualBrush TextCommandInputBoxBackground
        {
            get { return Globals.textCommandInputBoxBackground; }
        }

        private static ThicknessConverter thickConverter;

        public static ThicknessConverter ThickConverter
        {
            get { return Globals.thickConverter; }
        }


        private static readonly ObservableCollection<FontInfo> systemFontInfosCollection = new ObservableCollection<FontInfo>();
        /// <summary>
        /// 系统支持的字体的名称列表。
        /// </summary>
        public static ObservableCollection<FontInfo> SystemFontInfosCollection
        {
            get { return Globals.systemFontInfosCollection; }
        }

        private static XmlConfigManager configManager;
        /// <summary>
        /// Xml配置文件管理器。
        /// </summary>
        public static XmlConfigManager ConfigManager
        {
            get
            {
                return configManager;
            }
        }

        /// <summary>
        /// 如果当前文件还未保存在磁盘，则返回 null。
        /// 如果当前文件存在，则返回与当前文件同名、同路径（但是无后缀名）的目录路径。
        /// 注意：不保证目录在磁盘上存在。
        /// </summary>
        public static string PathOfWorkspace
        {
            get
            {
                try
                {
                    var fi = new System.IO.FileInfo(Globals.MainWindow.EditorManager.FullPathOfDiskFile);
                    var dPath = fi.Directory.FullName;
                    if (dPath.EndsWith("\\") == false)
                        dPath += "\\";
                    return dPath + fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length) + "\\";
                }
                catch
                {
                    return null;
                }
            }
        }

        public static string PathOfParentDirectory
        {
            get
            {
                try
                {
                    var fi = new System.IO.FileInfo(Globals.MainWindow.EditorManager.FullPathOfDiskFile);
                    var dPath = fi.Directory.FullName;
                    if (dPath.EndsWith("\\") == false)
                        dPath += "\\";
                    return dPath;
                }
                catch
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 用于判断一个点在目标矩形的相对位置。这些位置包括四正向、四隅向、内部、未知。
        /// </summary>
        public static LocationArea GetLocationArea(Rect rect, Point pt)
        {
            if (pt.X < rect.X)
            {
                if (pt.Y < rect.Y) return LocationArea.LeftTop;
                if (pt.Y >= rect.Y && pt.Y < rect.Y + rect.Height) return LocationArea.Left;

                return LocationArea.LeftBottom;
            }

            if (pt.X >= rect.X && pt.X < rect.X + rect.Width)
            {
                if (pt.Y < rect.Y) return LocationArea.Top;
                if (pt.Y >= rect.Y && pt.Y < rect.Y + rect.Height) return LocationArea.In;

                return LocationArea.Bottom;
            }

            if (pt.X >= rect.X + rect.Width)
            {
                if (pt.Y < rect.Y) return LocationArea.RightTop;
                if (pt.Y >= rect.Y && pt.Y < rect.Y + rect.Height) return LocationArea.Right;

                return LocationArea.RightBottom;
            }

            return LocationArea.UnKnown;
        }

        /// <summary>
        /// 载入图像文件。
        /// </summary>
        /// <param name="imageFilePath"></param>
        /// <returns></returns>
        public static BitmapImage LoadBitmapImageFromFile(string imageFilePath)
        {
            if (File.Exists(imageFilePath) == false) return null;
            try
            {
                using (BinaryReader reader = new BinaryReader(File.Open(imageFilePath, FileMode.Open)))
                {
                    FileInfo fi = new FileInfo(imageFilePath);
                    byte[] bytes = reader.ReadBytes((int)fi.Length);
                    reader.Close();

                    var bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = new MemoryStream(bytes);
                    bitmapImage.EndInit();
                    return bitmapImage;
                }
            }
            catch (Exception ex)
            {
                LunarMessage.Warning(ex.Message);
                return null;
            }
        }
    }

    public class FontInfo
    {
        public string DefaultFontName
        {
            get
            {
                if (string.IsNullOrEmpty(this.localFontName))
                    return this.fontName;
                else return this.localFontName;
            }
        }

        private string fontName = "";

        public string FontName
        {
            get { return this.fontName; }
            set { this.fontName = value; }
        }


        private string localFontName = "";

        public string LocalFontName
        {
            get { return this.localFontName; }
            set { this.localFontName = value; }
        }

    }
}
